package org.spring.bean.factory.config;

import org.spring.bean.exceptions.BeansException;
import org.spring.bean.factory.BeanFactory;
import org.spring.bean.factory.ListableBeanFactory;
import org.spring.bean.factory.NoSuchBeanDefinitionException;

/**
 * 大多数可列出的bean工厂要实现的配置接口。
 * 除了 {@link ConfigurableBeanFactory} 之外，它还提供了分析和修改 bean 定义以及预实例化单例的工具。
 *
 * <p>{@link BeanFactory} 的这个子接口不适用于普通的应用程序代码：坚持使用 {@link BeanFactory} 或 {@link ListableBeanFactory}
 * 用于典型用例。这个接口只是为了允许框架内部的即插即用，即使在需要访问 bean 工厂配置方法时也是如此。
 *
 * @author 李坤
 * @date 2022/4/23 19:02
 */
public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

    /**
     * 返回指定 bean 的注册 BeanDefinition，允许访问其属性值和构造函数参数值（可以在 bean 工厂后期处理期间修改）。
     * <p>
     * 返回的 BeanDefinition 对象不应是副本，而是在工厂中注册的原始定义对象。这意味着如果需要，它应该可以转换为更具体的实现类型。
     * <p>
     * <b>注意：<b> 此方法<i>不<i> 考虑祖先工厂。它仅用于访问该工厂的本地 bean 定义。
     *
     * @param beanName bean的名字
     *
     * @return 注册的 BeanDefinition
     *
     * @throws NoSuchBeanDefinitionException 如果此工厂中没有定义给定名称的 bean
     */
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * 确保所有非惰性初始化的单例实例都被实例化，还要考虑{@link FactoryBean}。如果需要，通常在工厂设置结束时调用。
     *
     * @throws BeansException 如果不能创建一个单例bean。
     *                        注意:这可能在离开工厂时已经初始化了一些bean!
     *                        在这种情况下，调用{@link #destroySingletons()}来进行完全的清理。
     * @see #destroySingletons()
     */
    void preInstantiateSingletons() throws BeansException;

}
